ea5bae
@@ -58,6 +58,7 @@
import org.springframework.util.StringUtils;
  * @author Arjen Poutsma
  * @author Sebastien Deleuze
  * @author Brian Clozel
+ * @author Juergen Hoeller
  * @since 3.0
  */
 public class HttpHeaders implements MultiValueMap<String, String>, Serializable {
@@ -454,7 +455,7 @@
public class HttpHeaders implements MultiValueMap<String, String>, Serializable
 	 * Returns the value of the {@code Access-Control-Allow-Credentials} response header.
 	 */
 	public boolean getAccessControlAllowCredentials() {
-		return new Boolean(getFirst(ACCESS_CONTROL_ALLOW_CREDENTIALS));
+		return Boolean.parseBoolean(getFirst(ACCESS_CONTROL_ALLOW_CREDENTIALS));
 	}
 
 	/**
@@ -510,22 +511,6 @@
public class HttpHeaders implements MultiValueMap<String, String>, Serializable
 		return getFieldValues(ACCESS_CONTROL_ALLOW_ORIGIN);
 	}
 
-	protected String getFieldValues(String headerName) {
-		List<String> headerValues = this.headers.get(headerName);
-		if (headerValues != null) {
-			StringBuilder builder = new StringBuilder();
-			for (Iterator<String> iterator = headerValues.iterator(); iterator.hasNext(); ) {
-				String ifNoneMatch = iterator.next();
-				builder.append(ifNoneMatch);
-				if (iterator.hasNext()) {
-					builder.append(", ");
-				}
-			}
-			return builder.toString();
-		}
-		return null;
-	}
-
 	/**
 	 * Set the (new) value of the {@code Access-Control-Expose-Headers} response header.
 	 */
@@ -809,6 +794,7 @@
public class HttpHeaders implements MultiValueMap<String, String>, Serializable
 
 	/**
 	 * Set the (new) value of the {@code If-Match} header.
+	 * @since 4.3
 	 */
 	public void setIfMatch(String ifMatch) {
 		set(IF_MATCH, ifMatch);
@@ -816,55 +802,20 @@
public class HttpHeaders implements MultiValueMap<String, String>, Serializable
 
 	/**
 	 * Set the (new) value of the {@code If-Match} header.
+	 * @since 4.3
 	 */
 	public void setIfMatch(List<String> ifMatchList) {
 		set(IF_MATCH, toCommaDelimitedString(ifMatchList));
 	}
 
-	protected String toCommaDelimitedString(List<String> list) {
-		StringBuilder builder = new StringBuilder();
-		for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
-			String ifNoneMatch = iterator.next();
-			builder.append(ifNoneMatch);
-			if (iterator.hasNext()) {
-				builder.append(", ");
-			}
-		}
-		return builder.toString();
-	}
-
 	/**
 	 * Return the value of the {@code If-Match} header.
+	 * @since 4.3
 	 */
 	public List<String> getIfMatch() {
 		return getETagValuesAsList(IF_MATCH);
 	}
 
-	protected List<String> getETagValuesAsList(String headerName) {
-		List<String> values = get(headerName);
-		if (values != null) {
-			List<String> result = new ArrayList<String>();
-			for (String value : values) {
-				if (value != null) {
-					Matcher matcher = ETAG_HEADER_VALUE_PATTERN.matcher(value);
-					while (matcher.find()) {
-						if ("*".equals(matcher.group())) {
-							result.add(matcher.group());
-						}
-						else {
-							result.add(matcher.group(1));
-						}
-					}
-					if(result.size() == 0) {
-						throw new IllegalArgumentException("Could not parse '" + headerName + "' value=" + value);
-					}
-				}
-			}
-			return result;
-		}
-		return Collections.emptyList();
-	}
-
 	/**
 	 * Set the (new) value of the {@code If-Modified-Since} header.
 	 * <p>The date should be specified as the number of milliseconds since
@@ -904,32 +855,11 @@
public class HttpHeaders implements MultiValueMap<String, String>, Serializable
 		return getETagValuesAsList(IF_NONE_MATCH);
 	}
 
-	/**
-	 * Return all values of a given header name,
-	 * even if this header is set multiple times.
-	 * @since 4.3
-	 */
-	public List<String> getValuesAsList(String headerName) {
-		List<String> values = get(headerName);
-		if (values != null) {
-			List<String> result = new ArrayList<String>();
-			for (String value : values) {
-				if (value != null) {
-					String[] tokens = StringUtils.tokenizeToStringArray(value, ",");
-					for (String token : tokens) {
-						result.add(token);
-					}
-				}
-			}
-			return result;
-		}
-		return Collections.emptyList();
-	}
-
 	/**
 	 * Set the (new) value of the {@code If-Unmodified-Since} header.
 	 * <p>The date should be specified as the number of milliseconds since
 	 * January 1, 1970 GMT.
+	 * @since 4.3
 	 */
 	public void setIfUnmodifiedSince(long ifUnmodifiedSince) {
 		setDate(IF_UNMODIFIED_SINCE, ifUnmodifiedSince);
@@ -939,6 +869,7 @@
public class HttpHeaders implements MultiValueMap<String, String>, Serializable
 	 * Return the value of the {@code If-Unmodified-Since} header.
 	 * <p>The date is returned as the number of milliseconds since
 	 * January 1, 1970 GMT. Returns -1 when the date is unknown.
+	 * @since 4.3
 	 */
 	public long getIfUnmodifiedSince() {
 		return getFirstDate(IF_UNMODIFIED_SINCE, false);
@@ -1054,17 +985,31 @@
public class HttpHeaders implements MultiValueMap<String, String>, Serializable
 
 	/**
 	 * Return the request header names subject to content negotiation.
+	 * @since 4.3
 	 */
 	public List<String> getVary() {
 		return getValuesAsList(VARY);
 	}
 
+	/**
+	 * Set the given date under the given header name after formatting it as a string
+	 * using the pattern {@code "EEE, dd MMM yyyy HH:mm:ss zzz"}. The equivalent of
+	 * {@link #set(String, String)} but for date headers.
+	 * @since 3.2.4
+	 */
+	public void setDate(String headerName, long date) {
+		SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMATS[0], Locale.US);
+		dateFormat.setTimeZone(GMT);
+		set(headerName, dateFormat.format(new Date(date)));
+	}
+
 	/**
 	 * Parse the first header value for the given header name as a date,
 	 * return -1 if there is no value, or raise {@link IllegalArgumentException}
 	 * if the value cannot be parsed as a date.
 	 * @param headerName the header name
 	 * @return the parsed date header, or -1 if none
+	 * @since 3.2.4
 	 */
 	public long getFirstDate(String headerName) {
 		return getFirstDate(headerName, true);
@@ -1109,16 +1054,92 @@
public class HttpHeaders implements MultiValueMap<String, String>, Serializable
 	}
 
 	/**
-	 * Set the given date under the given header name after formatting it as a string
-	 * using the pattern {@code "EEE, dd MMM yyyy HH:mm:ss zzz"}. The equivalent of
-	 * {@link #set(String, String)} but for date headers.
+	 * Return all values of a given header name,
+	 * even if this header is set multiple times.
+	 * @param headerName the header name
+	 * @return all associated values
+	 * @since 4.3
 	 */
-	public void setDate(String headerName, long date) {
-		SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMATS[0], Locale.US);
-		dateFormat.setTimeZone(GMT);
-		set(headerName, dateFormat.format(new Date(date)));
+	public List<String> getValuesAsList(String headerName) {
+		List<String> values = get(headerName);
+		if (values != null) {
+			List<String> result = new ArrayList<String>();
+			for (String value : values) {
+				if (value != null) {
+					String[] tokens = StringUtils.tokenizeToStringArray(value, ",");
+					for (String token : tokens) {
+						result.add(token);
+					}
+				}
+			}
+			return result;
+		}
+		return Collections.emptyList();
+	}
+
+	/**
+	 * Retrieve a combined result from the field values of the ETag header.
+	 * @param headerName the header name
+	 * @return the combined result
+	 * @since 4.3
+	 */
+	protected List<String> getETagValuesAsList(String headerName) {
+		List<String> values = get(headerName);
+		if (values != null) {
+			List<String> result = new ArrayList<String>();
+			for (String value : values) {
+				if (value != null) {
+					Matcher matcher = ETAG_HEADER_VALUE_PATTERN.matcher(value);
+					while (matcher.find()) {
+						if ("*".equals(matcher.group())) {
+							result.add(matcher.group());
+						}
+						else {
+							result.add(matcher.group(1));
+						}
+					}
+					if (result.isEmpty()) {
+						throw new IllegalArgumentException(
+								"Could not parse header '" + headerName + "' with value '" + value + "'");
+					}
+				}
+			}
+			return result;
+		}
+		return Collections.emptyList();
 	}
 
+	/**
+	 * Retrieve a combined result from the field values of multi-valued headers.
+	 * @param headerName the header name
+	 * @return the combined result
+	 * @since 4.3
+	 */
+	protected String getFieldValues(String headerName) {
+		List<String> headerValues = get(headerName);
+		return (headerValues != null ? toCommaDelimitedString(headerValues) : null);
+	}
+
+	/**
+	 * Turn the given list of header values into a comma-delimited result.
+	 * @param headerValues the list of header values
+	 * @return a combined result with comma delimitation
+	 */
+	protected String toCommaDelimitedString(List<String> headerValues) {
+		StringBuilder builder = new StringBuilder();
+		for (Iterator<String> it = headerValues.iterator(); it.hasNext(); ) {
+			String val = it.next();
+			builder.append(val);
+			if (it.hasNext()) {
+				builder.append(", ");
+			}
+		}
+		return builder.toString();
+	}
+
+
+	// MultiValueMap implementation
+
 	/**
 	 * Return the first header value for the given header name, if any.
 	 * @param headerName the header name
